import time
import subprocess
import uploadpyfile
import comallAuto
import signal
import threading

class TimeoutError(Exception):
    pass

def command(cmd, timeout=1):
    """执行命令cmd，返回命令输出的内容。
    如果超时将会抛出TimeoutError异常。
    如果在超时前执行Ctrl+C，将会中断命令的执行。
    cmd - 要执行的命令
    timeout - 最长等待时间，单位：秒
    """
    
    def run_command():
        nonlocal cmd, timeout, stop_event
        try:
            # 启动子进程，使用start_new_session=True确保子进程是进程组的组长
            p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,stdin=subprocess.DEVNULL, bufsize=-1, start_new_session=True)
            t_beginning = time.time()
            seconds_passed = 0
            while not stop_event.is_set():
                # 检查子进程是否已经结束
                if p.poll() is not None:
                    break
                # 计算已经经过的时间
                seconds_passed = time.time() - t_beginning
                # 检查是否超时
                if timeout and seconds_passed > timeout:
                    # 使用process.send_signal(signal.SIGINT)模拟Ctrl+C中断
                    p.send_signal(signal.CTRL_C_EVENT)
                    time.sleep(1)
                    # 检查进程是否在调用send_signal后结束
                    if p.poll() is None:
                        # 如果进程没有结束，使用process.kill()强制终止
                        p.kill()
                    raise TimeoutError(cmd, timeout)
                time.sleep(0.1)
            return p.stdout.read()
        except Exception as e:
            print(f"Error in run_command: {e}")
            return None

    # 创建事件对象，用于通知子线程退出
    stop_event = threading.Event()

    def signal_handler(sig, frame):
        # 捕获 Ctrl+C 信号，设置事件通知子线程退出
        stop_event.set()

    # 注册 Ctrl+C 信号处理程序
    signal.signal(signal.SIGINT, signal_handler)

    # 创建新线程并运行命令
    thread = threading.Thread(target=run_command)
    thread.start()

    try:
        thread.join(timeout)
    except KeyboardInterrupt:
        pass  # 在这里忽略 Ctrl+C 信号

    if thread.is_alive():
        # 如果线程仍在运行，说明超时或收到 Ctrl+C 信号
        thread.join()  # 等待线程结束
        time.sleep(0.1)
        raise TimeoutError(cmd, timeout)

def main():
    cmd = uploadpyfile.getComPort()
    print(cmd)
    try:
        command(cmd, 3)
    except TimeoutError as e:
        print(f"TimeoutError: {e}")
        print('timeout 1')
    time.sleep(1)
    try:
        print('try 2 ')
        command(cmd, 3)
    except TimeoutError as e:
        print(f"TimeoutError: {e}")
        print('timeout 2')
    time.sleep(0.1)
    # Code after the try-except block, it will be executed regardless of whether there was a timeout or not
    for i in range(3):
        print(3 - i)
        time.sleep(1)
    comallAuto.reset()
    for i in range(3):
        print(3 - i)
        time.sleep(1)
    comallAuto.reset()
    for i in range(3):
        print(3 - i)
        time.sleep(1)
    # 按任意键退出
    input("关闭窗口或者按回车键退出...")


if __name__ == '__main__':
    main()
